/**手写 Promise（含 all、race、finally）
 *
 *  手写 Promise 的步骤如下：
 *  1.构造函数
 *  2.添加状态（pending/rejected/fulfilled）及成功的值、失败的原因
 *  3.then方法(异步调用then方法传入的成功失败回调函数、多次调用then)
 *  4.异步任务
 *  5.链式调用
 * 
 *  1. MyPromise 类的构造函数
    初始化 Promise 的状态为 pending，并定义了 value 和 reason 分别用于存储成功的值和失败的原因。
    实现了 resolve 和 reject 方法，用于改变 Promise 的状态。
    执行 executor 函数，并捕获可能抛出的错误。

    2. then 方法
    处理 onFulfilled 和 onRejected 不是函数的情况。
    返回一个新的 MyPromise 实例，根据当前 Promise 的状态，异步执行回调函数。
    调用 resolvePromise 函数处理 then 方法的返回值。

    3. catch 方法
    调用 then 方法，只处理失败的情况。

    4. Promise.all 方法
    接收一个 Promise 数组，返回一个新的 Promise。
    当所有 Promise 都成功完成时，将结果数组作为新 Promise 的值进行 resolve。
    只要有一个 Promise 失败，就将该失败原因作为新 Promise 的错误进行 reject。

    5. Promise.race 方法
    接收一个 Promise 数组，返回一个新的 Promise。
    只要有一个 Promise 成功或失败，就将其结果或错误作为新 Promise 的值或错误进行 resolve 或 reject。

    6. Promise.prototype.finally 方法
    无论 Promise 状态如何，都会执行传入的回调函数。
    回调函数执行完毕后，返回原 Promise 的结果或错误。

    7. resolvePromise 函数
    用于处理 then 方法的返回值，避免循环引用，处理 thenable 对象。
    通过以上代码，我们实现了一个基本的 Promise 类，并包含了 Promise.all、Promise.race 和 Promise.prototype.finally 方法。
 */
// 定义 Promise 的三种状态
export const PENDING = 'pending';
export const FULFILLED = 'fulfilled';
export const REJECTED = 'rejected';
// 异步任务
const runAsyncTask = callback => {
  if (typeof queueMicrotask === 'function') {
    queueMicrotask(callback);
  } else if (typeof MutationObserver === 'function') {
    const observer = new MutationObserver(callback);
    const divNode = document.createTextNode('div');
    observer.observe(divNode, {
      childList: true
    });
    divNode.innerText = '1';
  } else {
    setTimeout(callback, 0);
  }
};
// 处理 then 方法的返回值
const resolvePromise = (promise2, x, resolve, reject) => {
  if (x === promise2) {
    throw new TypeError('Chaining cycle detected for promise #<Promise>');
  }
  if (x instanceof HMPromise) {
    // 处理返回值是Promise的情况
    x.then(value => resolvePromise(promise2, value, resolve, reject), reject);
    // x.then(
    //   res => resolve(res),
    //   error => reject(error)
    // );
  } else {
    resolve(x);
  }
};

class HMPromise {
  status = PENDING;
  value = undefined;
  reason = undefined;
  #onFulfilledCallbacks = [];
  #onRejectedCallbacks = [];
  constructor(executor) {
    // 改状态
    const resolve = value => {
      if (this.status === PENDING) {
        this.status = FULFILLED;
        this.value = value;
        this.#onFulfilledCallbacks.forEach(callback => callback(this.value));
      }
    };
    // 改状态
    const reject = reason => {
      if (this.status === PENDING) {
        this.status = REJECTED;
        this.reason = reason;
        this.#onRejectedCallbacks.forEach(callback => callback(this.reason));
      }
    };
    try {
      executor(resolve, reject);
    } catch (error) {
      reject(error);
    }
  }
  then(onFulfilled, onRejected) {
    // 处理 onFulfilled 不是函数的情况，onRejected 不是函数的情况
    onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value;
    onRejected =
      typeof onRejected === 'function'
        ? onRejected
        : x => {
            throw x;
          };
    // 执行onFulfilled 或 onRejected:
    //    1.状态可能异步更新
    //    2.可能多次调用then方法会多次传入回调，所有要收集回调函数

    //    1.返回Promise实例
    const p2 = new HMPromise((resolve, reject) => {
      const handleResolve = () => {
        //    2.获取返回值
        //       2.1 处理返回值
        //       2.2 处理异常
        try {
          const x = onFulfilled(this.value);
          // console.log('resolve', x);
          resolvePromise(p2, x, resolve, reject);
        } catch (error) {
          // console.log('捕获异常');
          reject(error);
        }
      };
      const handleReject = () => {
        try {
          const x = onRejected(this.reason);
          // console.log('reject', x);
          resolvePromise(p2, x, resolve, reject);
        } catch (error) {
          reject(error);
        }
      };

      if (this.status === FULFILLED) {
        runAsyncTask(() => {
          handleResolve();
        });
      } else if (this.status === REJECTED) {
        runAsyncTask(() => {
          handleReject();
        });
      } else if (this.status === PENDING) {
        // console.log('PENDING');
        // 3.异步执行onFulfilled 或 onRejected
        this.#onFulfilledCallbacks.push(() => {
          runAsyncTask(() => {
            handleResolve();
          });
        });
        this.#onRejectedCallbacks.push(() => {
          runAsyncTask(() => {
            handleReject();
          });
        });
      }
    });
    return p2;
  }
  catch(onRejected) {
    return this.then(null, onRejected);
  }
  finally(onFinally) {
    return this.then(onFinally, onFinally);
  }

  // 如果是Promise实例，直接返回；否则返回一个新的Promise实例
  static resolve(value) {
    if (value instanceof HMPromise) {
      return value;
    }
    return new HMPromise(resolve => {
      resolve(value);
    });
  }
  // 返回一个失败的Promise实例
  static reject(reason) {
    return new HMPromise((resolve, reject) => {
      reject(reason);
    });
  }
  // 处理多个Promise实例，返回一个新的Promise实例
  static race(promises) {
    return new HMPromise((resolve, reject) => {
      if (!Array.isArray(promises)) {
        return reject(new TypeError('Arugument is not iterable'));
      }
      promises.forEach(promise => {
        HMPromise.resolve(promise).then(
          value => {
            resolve(value);
          },
          error => {
            reject(error);
          }
        );
      });
    });
  }

  // 处理多个Promise实例，返回一个新的Promise实例，
  // 执行所有的Promise实例，记录每个的状态和内容
  // 1.返回一个新的Promise实例
  // 2.不是数组rejcte错误信息
  // 3.空数组直接兑现
  // 4.遍历promises数组：记录结果：索引记录顺序、记录全部兑现：根据兑现次数是否等于数组长度；
  // 5.有失败直接reject
  static all(promises) {
    return new HMPromise((resolve, reject) => {
      if (!Array.isArray(promises)) {
        return reject(new TypeError('Arugument is not iterable'));
      }
      if (promises.length === 0) {
        resolve(promises);
      }
      const result = [];
      let count = 0;
      promises.forEach((promise, index) => {
        HMPromise.resolve(promise).then(
          value => {
            result[index] = value;
            count++;
            if (count === promises.length) {
              resolve(result);
            }
          },
          error => {
            reject(error);
          }
        );
      });
    });
  }
  // 处理多个Promise实例，返回一个新的Promise实例，
  // 当所有的Promise实例都成功时才成功; 只要有一个失败，就失败
  // 1.返回一个新的Promise实例
  // 2.不是数组rejcte错误信息
  // 3.空数组直接兑现
  // 4.遍历promises数组：记录结果：索引记录顺序、记录全部兑现：根据兑现次数是否等于数组长度；
  // 5.成功失败都是reslove
  static allSettled(promises) {
    return new HMPromise((resolve, reject) => {
      const result = [];
      let count = 0;
      promises.forEach(promise => {
        promise.then(
          value => {
            result[index] = {
              status: FULFILLED,
              value
            };
            count++;
            if (count === promises.length) {
              resolve(result);
            }
          },
          error => {
            result[index] = {
              status: REJECTED,
              reason: error
            };
            count++;
            if (count === promises.length) {
              resolve(result);
            }
          }
        );
      });
    });
  }
  static any(promises) {
    return new HMPromise((resolve, reject) => {});
  }
}

const p = new HMPromise((resolve, reject) => {
  // resolve(1);
  // reject(2);
  // throw 'throw-error';
  setTimeout(() => {
    resolve(1);
    // reject(2);
  }, 3000);
});
// const p2 = new HMPromise((resolve, reject) => {
//   setTimeout(() => {
//     resolve(2);
//     // reject(2);
//   }, 2000);
// });
// HMPromise.all([p, p2]).then(
//   value => {
//     console.log('all', value);
//   },
//   error => {
//     console.log('all-error', error);
//   }
// );
// p.then(
//   value => {
//     console.log('成功回调1', value);
//     return new HMPromise((resolve, reject) => {
//       resolve(222222222);
//     });
//     // throw 'err';
//     return 1;
//   },
//   error => {
//     console.log('失败回调1', error);
//   }
// ).then(
//   value => {
//     // console.log('成功回调1完成后的2', value);
//   },
//   error => {
//     // console.log('失败回调2', error);
//   }
// );
// const p1 = p
//   .then(
//     res => {
//       console.log('成功回调1', res);
//       // throw 'error'; // 处理异常
//       // return p2; // 与当前Promise实例相同，会循环引用，抛出异常
//       // return 2; // 返回一个普通值
//       // return new HMPromise((resolve, reject) => {
//       //   reject(2222);
//       //   // resolve(222222222);
//       // }); // 返回一个HMPromise实例
//     }
//     // error => {
//     //   console.log('失败回调1', error);
//     //   // throw 'error'; // 处理异常
//     //   // return p2; // 与当前Promise实例相同，会循环引用，抛出异常
//     //   // return 2; // 返回一个普通值
//     //   // return new HMPromise((resolve, reject) => {
//     //   //   reject(2222);
//     //   //   // resolve(222222222);
//     //   // }); // 返回一个HMPromise实例
//     // }
//   )
//   .catch(err => {
//     console.log('err', err);
//   })
//   .finally(() => {
//     console.log('finally');
//   });
// p2.then(
//   value => {
//     console.log('p2-res', value);
//   },
//   error => {
//     console.log('p2-err', error);
//   }
// );

// const op = new Promise((resolve, reject) => {
//   // setTimeout(() => {
//   resolve(1);
//   // reject(2);
//   // }, 1000);
// });
// setTimeout(() => {
//   op.then(
//     value => {
//       // console.log('原生-成功回调1', value);
//       return new Promise((resolve, reject) => {
//         resolve(222222222);
//       });
//     },
//     error => {
//       // console.log('原生-失败回调1', error);
//     }
//   ).then(
//     value => {
//       // console.log('原生-成功回调1完成后', value);
//     },
//     error => {
//       // console.log('原生-失败回调2', error);
//     }
//   );

//   const op2 = op.then(res => {
//     return p2;
//   });
//   op.then(
//     value => {
//       // console.log('原生-成功回调1完成后', value);
//     }
//     // error => {
//     //   console.log('原生-error', error);
//     // }
//   );
// }, 1000);

console.log('bottom');
